package es.decloud.model;

import static javax.persistence.GenerationType.IDENTITY;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.hibernate.search.annotations.DocumentId;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;

@Entity
@Table(name = "alumno")
@Indexed
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class Alumno extends BaseObject implements Serializable {

	private static final long serialVersionUID = 5754394179102042185L;

	private Long id;
	private Centro centro;
	private Aula aula;
	private String nombre;
	private String apellido1;
	private String apellido2;
	private byte[] foto;
	private char sexo;
	private Date fechaNacimiento;
	private String alergias;
	private String observaciones;
	private Date fechaBaja;
	private Set<Evento> eventos = new HashSet<>(0);
	private Set<Autorizado> autorizados = new HashSet<>(0);
	private Set<CursoEscolar> cursosEscolares = new HashSet<>(0);
	private Set<Tutor> tutores = new HashSet<>(0);

	public Alumno() {
	}

	public Alumno(Centro centro, Aula aula, String nombre, String apellido1, char sexo, Date fechaNacimiento) {
		this.centro = centro;
		this.aula = aula;
		this.nombre = nombre;
		this.apellido1 = apellido1;
		this.sexo = sexo;
		this.fechaNacimiento = fechaNacimiento;
	}

	public Alumno(Centro centro, Aula aula, String nombre, String apellido1, String apellido2, byte[] foto, char sexo,
			Date fechaNacimiento, String alergias, String observaciones, Date fechaBaja, Set<Evento> eventos,
			Set<Autorizado> autorizados, Set<CursoEscolar> cursosEscolares, Set<Tutor> tutores) {
		this.centro = centro;
		this.aula = aula;
		this.nombre = nombre;
		this.apellido1 = apellido1;
		this.apellido2 = apellido2;
		this.foto = foto;
		this.sexo = sexo;
		this.fechaNacimiento = fechaNacimiento;
		this.alergias = alergias;
		this.observaciones = observaciones;
		this.fechaBaja = fechaBaja;
		this.eventos = eventos;
		this.autorizados = autorizados;
		this.cursosEscolares = cursosEscolares;
		this.tutores = tutores;
	}

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "id", unique = true, nullable = false)
	@DocumentId
	public Long getId() {
		return this.id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@ManyToOne
	@JoinColumn(name = "centro_id", nullable = false)
	public Centro getCentro() {
		return this.centro;
	}

	public void setCentro(Centro centro) {
		this.centro = centro;
	}

	@ManyToOne
	@JoinColumn(name = "aula_id", nullable = false)
	public Aula getAula() {
		return this.aula;
	}

	public void setAula(Aula aula) {
		this.aula = aula;
	}

	@Column(name = "nombre", nullable = false, length = 100)
	@Field
	public String getNombre() {
		return this.nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	@Column(name = "apellido1", nullable = false, length = 100)
	@Field
	public String getApellido1() {
		return this.apellido1;
	}

	public void setApellido1(String apellido1) {
		this.apellido1 = apellido1;
	}

	@Column(name = "apellido2", length = 100)
	@Field
	public String getApellido2() {
		return this.apellido2;
	}

	public void setApellido2(String apellido2) {
		this.apellido2 = apellido2;
	}

	/**
	 * Devuelve el nombre completo
	 */
	@Transient
	public String getNombreCompleto() {
		return new StringBuilder().append(nombre).append(" ").append(apellido1).append(" ").append(apellido2)
				.toString();
	}

	@Lob
	@Column(name = "foto")
	public byte[] getFoto() {
		return this.foto;
	}

	public void setFoto(byte[] foto) {
		this.foto = foto;
	}

	@Column(name = "sexo", nullable = false, length = 1)
	public char getSexo() {
		return this.sexo;
	}

	public void setSexo(char sexo) {
		this.sexo = sexo;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "fecha_nacimiento", nullable = false, length = 10)
	@Field
	public Date getFechaNacimiento() {
		return this.fechaNacimiento;
	}

	public void setFechaNacimiento(Date fechaNacimiento) {
		this.fechaNacimiento = fechaNacimiento;
	}

	@Column(name = "alergias")
	@Field
	public String getAlergias() {
		return this.alergias;
	}

	public void setAlergias(String alergias) {
		this.alergias = alergias;
	}

	@Column(name = "observaciones", length = 1000)
	@Field
	public String getObservaciones() {
		return this.observaciones;
	}

	public void setObservaciones(String observaciones) {
		this.observaciones = observaciones;
	}

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "fecha_baja", length = 19)
	public Date getFechaBaja() {
		return this.fechaBaja;
	}

	public void setFechaBaja(Date fechaBaja) {
		this.fechaBaja = fechaBaja;
	}

	@OneToMany(mappedBy = "alumno")
	@JsonIgnore
	public Set<Evento> getEventos() {
		return this.eventos;
	}

	public void setEventos(Set<Evento> eventos) {
		this.eventos = eventos;
	}

	@OneToMany(mappedBy = "alumno")
	@JsonIgnore
	public Set<Autorizado> getAutorizados() {
		return this.autorizados;
	}

	public void setAutorizados(Set<Autorizado> autorizados) {
		this.autorizados = autorizados;
	}

	@ManyToMany
	@JoinTable(name = "alumno_cursoescolar", joinColumns = { @JoinColumn(name = "alumno_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "curso_id", nullable = false, updatable = false) })
	public Set<CursoEscolar> getCursosEscolares() {
		return this.cursosEscolares;
	}

	public void setCursosEscolares(Set<CursoEscolar> cursosEscolares) {
		this.cursosEscolares = cursosEscolares;
	}

	@OneToMany(mappedBy = "alumno")
	public Set<Tutor> getTutores() {
		return this.tutores;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((apellido1 == null) ? 0 : apellido1.hashCode());
		result = prime * result + ((apellido2 == null) ? 0 : apellido2.hashCode());
		result = prime * result + ((fechaNacimiento == null) ? 0 : fechaNacimiento.hashCode());
		result = prime * result + ((nombre == null) ? 0 : nombre.hashCode());
		result = prime * result + sexo;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Alumno other = (Alumno) obj;
		if (apellido1 == null) {
			if (other.apellido1 != null)
				return false;
		}
		else if (!apellido1.equals(other.apellido1))
			return false;
		if (apellido2 == null) {
			if (other.apellido2 != null)
				return false;
		}
		else if (!apellido2.equals(other.apellido2))
			return false;
		if (fechaNacimiento == null) {
			if (other.fechaNacimiento != null)
				return false;
		}
		else if (!fechaNacimiento.equals(other.fechaNacimiento))
			return false;
		if (nombre == null) {
			if (other.nombre != null)
				return false;
		}
		else if (!nombre.equals(other.nombre))
			return false;
		if (sexo != other.sexo)
			return false;
		return true;
	}

	public void setTutores(Set<Tutor> tutores) {
		this.tutores = tutores;
	}

	@Override
	public String toString() {
		return new ToStringBuilder(this).append("id", id).append("centro", centro).append("aula", aula)
				.append("nombre", nombre).append("apellido1", apellido1).append("apellido2", apellido2)
				.append("foto", Arrays.toString(foto)).append("sexo", sexo).append("fechaNacimiento", fechaNacimiento)
				.append("alergias", alergias).append("observaciones", observaciones).append("fechaBaja", fechaBaja)
				.toString();
	}

}
